#TODO: block Tcp Transport
#TODO: non-block Tcp Transport



from error import ConnectionStateError
import socket

class MockTransport(object):
    def __init__(self):
        self.__ip = "127.0.0.1"
        self.__port = 12345
        self.__is_connected = False
        self.__sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    def __del__(self):
        self.close()

    def remote(self, ip, port):
        if ip is not None and len(ip) > 1:
            self.__ip = ip
        if port is not None:
            self.__port = port
        return self

    def ip(self):
        return self.__ip
    def port(self):
        return self.__port

    def connect(self):
        if not self.__is_connected :
            self.__sock.connect((self.__ip, self.__port))
            self.__is_connected = True
        else:
            raise ConnectionStateError(self.is_connected())

    def disconnect(self):
        if self.__is_connected:
            self.__sock.shutdown(socket.SHUT_RDWR)
            self.__is_connected = False
        else:
            raise ConnectionStateError(self.is_connected())

    def is_connected(self):
        return self.__is_connected

    def send(self, byte_buffer):
        if self.__is_connected:
            if byte_buffer is not None and len(byte_buffer) > 0:
                return self.__sock.send(byte_buffer)
            else:
                return 0;
        else: 
            raise ConnectionStateError(self.is_connected())

    def recv(self, buf_size):
        if self.__is_connected:
            data = self.__sock.recv(buf_size)
            if len(data) == 0: # peer is disconnected
                assert(self.__is_connected == True)
                self.disconnect()
            return data
        else:
            raise ConnectionStateError(self.is_connected())

    def close(self):
        if self.__is_connected:
            self.disconnect()

        if self.__sock is not None:
            self.__sock.close()
            self.__sock = None
        

    def __str__(self):
        return "MockTransport:ip:{},port:{},is_connected:{}".format(self.__ip, self.__port, self.__is_connected)

    def handle(self):
        return self.__sock




import unittest 
class TestMockTransport(unittest.TestCase):
    def test_main(self):
        trans = MockTransport().remote("127.0.0.1", 12345)
        self.assertEqual(trans.ip(), "127.0.0.1")
        self.assertEqual(trans.port(), 12345)
        print(trans)

        trans.connect()
        self.assertTrue(trans.is_connected())
        print(trans)

        message = "hello world\n".encode("utf-8")
        for i in range(10):
            cnt = trans.send(message)
            self.assertEqual(len(message), cnt)

        """
        data = trans.recv(10)
        if len(data) > 0:
            print(data.decode('utf-8'))
        else:
            self.assertFalse(self.is_connected())
        """

        trans.disconnect()
        self.assertFalse(trans.is_connected())

        trans.close() # for release resource 


if __name__ == "__main__":
    unittest.main(verbosity=2)



